// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.Collections;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;
import sun.misc.Unsafe;

public class NonBlockingSetInt extends AbstractSet<Integer> implements Serializable {
    private static final long serialVersionUID = 1234123412341234123L;
    private static final Unsafe _unsafe = UtilUnsafe.getUnsafe();
    private static final long _nbsi_offset;
    private transient NonBlockingSetInt.NBSI _nbsi;

    private final boolean CAS_nbsi(NonBlockingSetInt.NBSI nBSI0, NonBlockingSetInt.NBSI nBSI1) {
        return _unsafe.compareAndSwapObject(this, _nbsi_offset, nBSI0, nBSI1);
    }

    public NonBlockingSetInt() {
        this._nbsi = new NonBlockingSetInt.NBSI(63, new Counter(), this);
    }

    private NonBlockingSetInt(NonBlockingSetInt nonBlockingSetInt2, NonBlockingSetInt nonBlockingSetInt1) {
        this._nbsi = new NonBlockingSetInt.NBSI(nonBlockingSetInt2._nbsi, nonBlockingSetInt1._nbsi, new Counter(), this);
    }

    public boolean add(Integer i) {
        return this.add(i.intValue());
    }

    public boolean contains(Object o) {
        return o instanceof Integer ? this.contains(((Integer)o).intValue()) : false;
    }

    public boolean remove(Object o) {
        return o instanceof Integer ? this.remove(((Integer)o).intValue()) : false;
    }

    public boolean add(int i) {
        if (i < 0) {
            throw new IllegalArgumentException(i + "");
        } else {
            return this._nbsi.add(i);
        }
    }

    public boolean contains(int i) {
        return i < 0 ? false : this._nbsi.contains(i);
    }

    public boolean remove(int i) {
        return i < 0 ? false : this._nbsi.remove(i);
    }

    public int size() {
        return this._nbsi.size();
    }

    public void clear() {
        NonBlockingSetInt.NBSI nBSI = new NonBlockingSetInt.NBSI(63, new Counter(), this);

        while (!this.CAS_nbsi(this._nbsi, nBSI)) {
        }
    }

    public int sizeInBytes() {
        return this._nbsi.sizeInBytes();
    }

    public NonBlockingSetInt intersect(NonBlockingSetInt op) {
        NonBlockingSetInt nonBlockingSetInt = new NonBlockingSetInt(this, op);
        nonBlockingSetInt._nbsi.intersect(nonBlockingSetInt._nbsi, this._nbsi, op._nbsi);
        return nonBlockingSetInt;
    }

    public NonBlockingSetInt union(NonBlockingSetInt op) {
        NonBlockingSetInt nonBlockingSetInt = new NonBlockingSetInt(this, op);
        nonBlockingSetInt._nbsi.union(nonBlockingSetInt._nbsi, this._nbsi, op._nbsi);
        return nonBlockingSetInt;
    }

    public void print() {
        this._nbsi.print(0);
    }

    public Iterator<Integer> iterator() {
        return new NonBlockingSetInt.iter();
    }

    public IntIterator intIterator() {
        return new NonBlockingSetInt.NBSIIntIterator();
    }

    private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
        objectOutputStream.defaultWriteObject();
        NonBlockingSetInt.NBSI nBSI = this._nbsi;
        int int0 = this._nbsi._bits.length << 6;
        objectOutputStream.writeInt(int0);

        for (int int1 = 0; int1 < int0; int1++) {
            objectOutputStream.writeBoolean(this._nbsi.contains(int1));
        }
    }

    private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        objectInputStream.defaultReadObject();
        int int0 = objectInputStream.readInt();
        this._nbsi = new NonBlockingSetInt.NBSI(int0, new Counter(), this);

        for (int int1 = 0; int1 < int0; int1++) {
            if (objectInputStream.readBoolean()) {
                this._nbsi.add(int1);
            }
        }
    }

    static {
        Field field = null;

        try {
            field = NonBlockingSetInt.class.getDeclaredField("_nbsi");
        } catch (NoSuchFieldException noSuchFieldException) {
        }

        _nbsi_offset = _unsafe.objectFieldOffset(field);
    }

    private static final class NBSI {
        private final transient NonBlockingSetInt _non_blocking_set_int;
        private final transient Counter _size;
        private final long[] _bits;
        private static final int _Lbase = NonBlockingSetInt._unsafe.arrayBaseOffset(long[].class);
        private static final int _Lscale = NonBlockingSetInt._unsafe.arrayIndexScale(long[].class);
        private NonBlockingSetInt.NBSI _new;
        private static final long _new_offset;
        private final transient AtomicInteger _copyIdx;
        private final transient AtomicInteger _copyDone;
        private final transient int _sum_bits_length;
        private final NonBlockingSetInt.NBSI _nbsi64;

        private static long rawIndex(long[] _long, int _int) {
            assert _int >= 0 && _int < _long.length;

            return (long)(_Lbase + _int * _Lscale);
        }

        private final boolean CAS(int _int, long long0, long long1) {
            return NonBlockingSetInt._unsafe.compareAndSwapLong(this._bits, rawIndex(this._bits, _int), long0, long1);
        }

        private final boolean CAS_new(NonBlockingSetInt.NBSI nBSI1) {
            return NonBlockingSetInt._unsafe.compareAndSwapObject(this, _new_offset, null, nBSI1);
        }

        private static final long mask(int _int) {
            return 1L << (_int & 63);
        }

        private NBSI(int _int, Counter counter, NonBlockingSetInt nonBlockingSetInt) {
            this._non_blocking_set_int = nonBlockingSetInt;
            this._size = counter;
            this._copyIdx = counter == null ? null : new AtomicInteger();
            this._copyDone = counter == null ? null : new AtomicInteger();
            this._bits = new long[(int)((long)_int + 63L >>> 6)];
            this._nbsi64 = _int + 1 >>> 6 == 0 ? null : new NonBlockingSetInt.NBSI(_int + 1 >>> 6, null, null);
            this._sum_bits_length = this._bits.length + (this._nbsi64 == null ? 0 : this._nbsi64._sum_bits_length);
        }

        private NBSI(NonBlockingSetInt.NBSI nBSI2, NonBlockingSetInt.NBSI nBSI1, Counter counter, NonBlockingSetInt nonBlockingSetInt) {
            this._non_blocking_set_int = nonBlockingSetInt;
            this._size = counter;
            this._copyIdx = counter == null ? null : new AtomicInteger();
            this._copyDone = counter == null ? null : new AtomicInteger();
            if (!has_bits(nBSI2) && !has_bits(nBSI1)) {
                this._bits = null;
                this._nbsi64 = null;
                this._sum_bits_length = 0;
            } else {
                if (!has_bits(nBSI2)) {
                    this._bits = new long[nBSI1._bits.length];
                    this._nbsi64 = new NonBlockingSetInt.NBSI(null, nBSI1._nbsi64, null, null);
                } else if (!has_bits(nBSI1)) {
                    this._bits = new long[nBSI2._bits.length];
                    this._nbsi64 = new NonBlockingSetInt.NBSI(null, nBSI2._nbsi64, null, null);
                } else {
                    int _int = nBSI2._bits.length > nBSI1._bits.length ? nBSI2._bits.length : nBSI1._bits.length;
                    this._bits = new long[_int];
                    this._nbsi64 = new NonBlockingSetInt.NBSI(nBSI2._nbsi64, nBSI1._nbsi64, null, null);
                }

                this._sum_bits_length = this._bits.length + this._nbsi64._sum_bits_length;
            }
        }

        private static boolean has_bits(NonBlockingSetInt.NBSI nBSI) {
            return nBSI != null && nBSI._bits != null;
        }

        public boolean add(int int0) {
            if (int0 >> 6 >= this._bits.length) {
                return this.install_larger_new_bits(int0).help_copy().add(int0);
            } else {
                NonBlockingSetInt.NBSI nBSI1 = this;

                int int1;
                for (int1 = int0; (int1 & 63) == 63; int1 >>= 6) {
                    nBSI1 = nBSI1._nbsi64;
                }

                long long0 = mask(int1);

                long long1;
                do {
                    long1 = nBSI1._bits[int1 >> 6];
                    if (long1 < 0L) {
                        return this.help_copy_impl(int0).help_copy().add(int0);
                    }

                    if ((long1 & long0) != 0L) {
                        return false;
                    }
                } while (!nBSI1.CAS(int1 >> 6, long1, long1 | long0));

                this._size.add(1L);
                return true;
            }
        }

        public boolean remove(int int0) {
            if (int0 >> 6 >= this._bits.length) {
                return this._new == null ? false : this.help_copy().remove(int0);
            } else {
                NonBlockingSetInt.NBSI nBSI1 = this;

                int int1;
                for (int1 = int0; (int1 & 63) == 63; int1 >>= 6) {
                    nBSI1 = nBSI1._nbsi64;
                }

                long long0 = mask(int1);

                long long1;
                do {
                    long1 = nBSI1._bits[int1 >> 6];
                    if (long1 < 0L) {
                        return this.help_copy_impl(int0).help_copy().remove(int0);
                    }

                    if ((long1 & long0) == 0L) {
                        return false;
                    }
                } while (!nBSI1.CAS(int1 >> 6, long1, long1 & ~long0));

                this._size.add(-1L);
                return true;
            }
        }

        public boolean contains(int int0) {
            if (int0 >> 6 >= this._bits.length) {
                return this._new == null ? false : this.help_copy().contains(int0);
            } else {
                NonBlockingSetInt.NBSI nBSI1 = this;

                int int1;
                for (int1 = int0; (int1 & 63) == 63; int1 >>= 6) {
                    nBSI1 = nBSI1._nbsi64;
                }

                long long0 = mask(int1);
                long long1 = nBSI1._bits[int1 >> 6];
                return long1 < 0L ? this.help_copy_impl(int0).help_copy().contains(int0) : (long1 & long0) != 0L;
            }
        }

        public boolean intersect(NonBlockingSetInt.NBSI nBSI2, NonBlockingSetInt.NBSI nBSI1, NonBlockingSetInt.NBSI nBSI0) {
            if (has_bits(nBSI1) && has_bits(nBSI0)) {
                for (int _int = 0; _int < nBSI2._bits.length; _int++) {
                    long long0 = nBSI1.safe_read_word(_int, 0L);
                    long long1 = nBSI0.safe_read_word(_int, 0L);
                    nBSI2._bits[_int] = long0 & long1 & Long.MAX_VALUE;
                }

                return this.intersect(nBSI2._nbsi64, nBSI1._nbsi64, nBSI0._nbsi64);
            } else {
                return true;
            }
        }

        public boolean union(NonBlockingSetInt.NBSI nBSI2, NonBlockingSetInt.NBSI nBSI1, NonBlockingSetInt.NBSI nBSI0) {
            if (!has_bits(nBSI1) && !has_bits(nBSI0)) {
                return true;
            } else {
                if (has_bits(nBSI1) || has_bits(nBSI0)) {
                    for (int _int = 0; _int < nBSI2._bits.length; _int++) {
                        long long0 = nBSI1.safe_read_word(_int, 0L);
                        long long1 = nBSI0.safe_read_word(_int, 0L);
                        nBSI2._bits[_int] = (long0 | long1) & Long.MAX_VALUE;
                    }
                }

                return this.union(nBSI2._nbsi64, nBSI1._nbsi64, nBSI0._nbsi64);
            }
        }

        private long safe_read_word(int _int, long long0) {
            if (_int >= this._bits.length) {
                return long0;
            } else {
                long long1 = this._bits[_int];
                if (long1 < 0L) {
                    long1 = this.help_copy_impl(_int).help_copy()._bits[_int];
                }

                return long1;
            }
        }

        public int sizeInBytes() {
            return this._bits.length;
        }

        public int size() {
            return (int)this._size.get();
        }

        private NonBlockingSetInt.NBSI install_larger_new_bits(int var1) {
            if (this._new == null) {
                int _int = this._bits.length << 6 << 1;
                this.CAS_new(new NonBlockingSetInt.NBSI(_int, this._size, this._non_blocking_set_int));
            }

            return this;
        }

        private NonBlockingSetInt.NBSI help_copy() {
            NonBlockingSetInt.NBSI nBSI0 = this._non_blocking_set_int._nbsi;
            int int0 = nBSI0._copyIdx.getAndAdd(512);

            for (int int1 = 0; int1 < 8; int1++) {
                int int2 = int0 + int1 * 64;
                int2 %= nBSI0._bits.length << 6;
                nBSI0.help_copy_impl(int2);
                nBSI0.help_copy_impl(int2 + 63);
            }

            if (nBSI0._copyDone.get() == nBSI0._sum_bits_length && this._non_blocking_set_int.CAS_nbsi(nBSI0, nBSI0._new)) {
            }

            return this._new;
        }

        private NonBlockingSetInt.NBSI help_copy_impl(int int1) {
            NonBlockingSetInt.NBSI nBSI0 = this;
            NonBlockingSetInt.NBSI nBSI2 = this._new;
            if (nBSI2 == null) {
                return this;
            } else {
                int int0;
                for (int0 = int1; (int0 & 63) == 63; int0 >>= 6) {
                    nBSI0 = nBSI0._nbsi64;
                    nBSI2 = nBSI2._nbsi64;
                }

                long long0;
                for (long0 = nBSI0._bits[int0 >> 6]; long0 >= 0L; long0 = nBSI0._bits[int0 >> 6]) {
                    long long1 = long0;
                    long0 |= mask(63);
                    if (nBSI0.CAS(int0 >> 6, long1, long0)) {
                        if (long1 == 0L) {
                            this._copyDone.addAndGet(1);
                        }
                        break;
                    }
                }

                if (long0 != mask(63)) {
                    long long2 = nBSI2._bits[int0 >> 6];
                    if (long2 == 0L) {
                        long2 = long0 & ~mask(63);
                        if (!nBSI2.CAS(int0 >> 6, 0L, long2)) {
                            long2 = nBSI2._bits[int0 >> 6];
                        }

                        assert long2 != 0L;
                    }

                    if (nBSI0.CAS(int0 >> 6, long0, mask(63))) {
                        this._copyDone.addAndGet(1);
                    }
                }

                return this;
            }
        }

        private void print(int int1, String string) {
            for (int int0 = 0; int0 < int1; int0++) {
                System.out.print("  ");
            }

            System.out.println(string);
        }

        private void print(int int0) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("NBSI - _bits.len=");

            for (NonBlockingSetInt.NBSI nBSI0 = this; nBSI0 != null; nBSI0 = nBSI0._nbsi64) {
                stringBuffer.append(" " + nBSI0._bits.length);
            }

            this.print(int0, stringBuffer.toString());
            NonBlockingSetInt.NBSI nBSI2 = this;

            while (nBSI2 != null) {
                for (int int1 = 0; int1 < nBSI2._bits.length; int1++) {
                    System.out.print(Long.toHexString(nBSI2._bits[int1]) + " ");
                }

                nBSI2 = nBSI2._nbsi64;
                System.out.println();
            }

            if (this._copyIdx.get() != 0 || this._copyDone.get() != 0) {
                this.print(int0, "_copyIdx=" + this._copyIdx.get() + " _copyDone=" + this._copyDone.get() + " _words_to_cpy=" + this._sum_bits_length);
            }

            if (this._new != null) {
                this.print(int0, "__has_new - ");
                this._new.print(int0 + 1);
            }
        }

        static {
            Field field = null;

            try {
                field = NonBlockingSetInt.NBSI.class.getDeclaredField("_new");
            } catch (NoSuchFieldException noSuchFieldException) {
            }

            _new_offset = NonBlockingSetInt._unsafe.objectFieldOffset(field);
        }
    }

    private class NBSIIntIterator implements IntIterator {
        NonBlockingSetInt.NBSI nbsi;
        int index = -1;
        int prev = -1;

        NBSIIntIterator() {
            this.nbsi = NonBlockingSetInt.this._nbsi;
            this.advance();
        }

        private void advance() {
            do {
                this.index++;

                while (this.index >> 6 >= this.nbsi._bits.length) {
                    if (this.nbsi._new == null) {
                        this.index = -2;
                        return;
                    }

                    this.nbsi = this.nbsi._new;
                }
            } while (!this.nbsi.contains(this.index));
        }

        @Override
        public int next() {
            if (this.index == -1) {
                throw new NoSuchElementException();
            } else {
                this.prev = this.index;
                this.advance();
                return this.prev;
            }
        }

        @Override
        public boolean hasNext() {
            return this.index != -2;
        }

        public void remove() {
            if (this.prev == -1) {
                throw new IllegalStateException();
            } else {
                this.nbsi.remove(this.prev);
                this.prev = -1;
            }
        }
    }

    private class iter implements Iterator<Integer> {
        NonBlockingSetInt.NBSIIntIterator intIterator = NonBlockingSetInt.this.new NBSIIntIterator();

        iter() {
        }

        public boolean hasNext() {
            return this.intIterator.hasNext();
        }

        public Integer next() {
            return this.intIterator.next();
        }

        public void remove() {
            this.intIterator.remove();
        }
    }
}
